﻿using System;
using System.Drawing;
using System.Windows.Forms;
using Kyoh.Lib.WinForms;
using Kyoh.Lib.Win32API;

namespace Kyoh.Lib.WinForms
{
    /// <summary>レイヤードウィンドウを使用して、透明度のあるフォームを作成します。</summary>
    public partial class LayeredForm : Form
    {
        /// <summary><see cref="LayeredForm"/> クラスの新しいインスタンスを初期化します。</summary>
        public LayeredForm()
        {
            InitializeComponent();
        }

        /// <summary>このフォームをレイヤードウィンドウに変更し、指定されたビットマップを背景として表示します。</summary>
        /// <param name="bitmap">表示する背景のビットマップ。</param>
        public void SetLayeredWindow(Bitmap bitmap)
        {
            if(DesignMode)
                return;

            // GetDeviceContext
            var screenDc = IntPtr.Zero;
            var memDc = IntPtr.Zero;
            var hBitmap = IntPtr.Zero;
            var hOldBitmap = IntPtr.Zero;
            try
            {
                screenDc = NativeMethods.GetDC(IntPtr.Zero);
                memDc = NativeMethods.CreateCompatibleDC(screenDc);
                hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
                hOldBitmap = NativeMethods.SelectObject(memDc, hBitmap);

                // init BLENDFUNCTION
                var blend = new BlendFunction
                                {
                                    BlendOp = Constants.AC_SRC_OVER,
                                    BlendFlags = 0,
                                    SourceConstantAlpha = 255,
                                    AlphaFormat = Constants.AC_SRC_ALPHA
                                };

                // Update Layered Window
                Size = new Size(bitmap.Width, bitmap.Height);
                var pptDst = new Point(Left, Top);
                var psize = new Size(Width, Height);
                var pptSrc = new Point(0, 0);
                NativeMethods.UpdateLayeredWindow(Handle, screenDc, ref pptDst, ref psize, memDc,
                                    ref pptSrc, 0, ref blend, UpdateLayeredWindowFlags.Alpha);

            }
            finally
            {
                if (screenDc != IntPtr.Zero)
                    NativeMethods.ReleaseDC(IntPtr.Zero, screenDc);
                if (hBitmap != IntPtr.Zero)
                {
                    NativeMethods.SelectObject(memDc, hOldBitmap);
                    NativeMethods.DeleteObject(hBitmap);
                }
                if (memDc != IntPtr.Zero)
                    NativeMethods.DeleteDC(memDc);
            }
        }

        /// <summary>Win32APIにおいて使用するウィンドウパラメータを取得します。</summary>
        protected override CreateParams CreateParams
        {
            get
            {
                var cp = base.CreateParams;

                if (DesignMode)
                    return cp;

                cp.ExStyle = cp.ExStyle | (int)CreateWindowExStyle.Layered;
                // 必要に応じてCreateWindowStyle.TRANSPARENT をつける
                if (FormBorderStyle != FormBorderStyle.None)
                {
                    cp.Style = cp.Style & (~(int)CreateWindowStyle.Border);
                    cp.Style = cp.Style & (~(int)CreateWindowStyle.ThickFrame);
                }

                return cp;
            }
        }
    }
}
